package com.skyyan.netty.jjf.codec;

import com.skyyan.netty.jjf.protocol.*;
import io.netty.buffer.ByteBufUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 消息工厂，根据AFN码创建对应的Message对象
 * 支持扩展新的报文类型
 * @author skyyan
 */
public class MessageFactory {

    private static final Logger log = LoggerFactory.getLogger(MessageFactory.class);

    /**
     * 根据控制域、地址域、AFN和用户数据创建对应的Message对象
     * @param control 控制域
     * @param address 地址域 (长度根据报文类型而定：标准9字节或扩展20字节)
     * @param afn 应用层功能码
     * @param userData 用户数据
     * @return 对应的Message对象，如果AFN未知则返回null
     */
    public static Message createMessage(byte control, byte[] address, byte afn, byte[] userData) {
        // 使用 Netty 的工具类将 byte[] 转换为16进制字符串
        String addressHex = address == null ? "null" : ByteBufUtil.hexDump(address);
        // 处理 userData 为 null 的情况
        String userDataHex = userData == null ? "null" : ByteBufUtil.hexDump(userData);

        log.info("✅ MessageFactory 接收到完整数据包 - control: 0x{}, afn: 0x{}, address (Hex): {}, userData (Hex): {}",
                String.format("%02X", control), // 格式化 control 为2位大写16进制
                String.format("%02X", afn),     // 格式化 afn 为2位大写16进制
                addressHex,                     // 已处理 null 的 address 16进制字符串
                userDataHex);                   // 已处理 null 的 userData 16进制字符串

        try {
            switch (afn) {
                //0 设备注册报文
                case FrameConstants.AFN_REGISTER:
                    log.debug("收到 C.4 注册 报文，AFN: 0x{}", String.format("%02X", afn));
                    // 注册报文和其响应报文使用相同的AFN，通过控制域区分
                    if (control == FrameConstants.CONTROL_UPLINK) {
                        return new RegisterMessage.Uplink(address);
                    } else {
                        return new RegisterMessage.Downlink(null,userData);
                    }
                //1.设备注册确认报文
                case FrameConstants.AFN_REGISTER_CONFIRM:
                    // C.5 注册确认报文
                    log.debug("收到 C.5 注册确认 报文，AFN: 0x{}", String.format("%02X", afn));
                    if(control ==FrameConstants.CONTROL_UPLINK){
                        return new RegisterConfirmMessage.Uplink(address,userData);
                    }else{
                        return new RegisterConfirmMessage.Downlink(address,userData);
                    }
                case FrameConstants.AFN_BALANCE_QUERY:
                    log.debug("收到 C.6余额查询 报文，AFN: 0x{}", String.format("%02X", afn));
                    // C.6 余额查询报文 (地址域19字节)
                    if (control == FrameConstants.CONTROL_UPLINK) {
                        return new BalanceQueryMessage.Uplink(address, userData);
                    } else {
                        return new BalanceQueryMessage.Downlink(address, userData);
                    }
                case FrameConstants.AFN_RECHARGE:
                    // C.7 充值报文
                    log.info("收到 C.7充值 报文，AFN: 0x{}", String.format("%02X", afn));
                    if (control == FrameConstants.CONTROL_UPLINK) {
                        return new RechargeMessage.Uplink(address, userData);
                    } else {
                        return new RechargeMessage.Downlink(address, userData);
                    }
                case FrameConstants.AFN_WATER_ELECTRICITY_PRICE_QUERY:
                    // C.8 阶梯水电价查询
                    log.debug("收到  C.8 阶梯水电价查询 报文，AFN: 0x{}", String.format("%02X", afn));
                    return createGenericMessage(control, address, afn, userData);
                case FrameConstants.AFN_OPEN_CARD:
                    // C.9 开卡报文
                    log.debug("收到 C.9 开卡 报文，AFN: 0x{}", String.format("%02X", afn));
                    if (control == FrameConstants.CONTROL_UPLINK) {
                        return new OpenCardMessage.Uplink(address,userData);
                    } else {
                        return new OpenCardMessage.Downlink(address, userData);
                    }
                default:
                    log.warn("未知的AFN码: 0x{}", String.format("%02X", afn));
                    return null;
            }
        } catch (Exception e) {
            log.error("创建消息对象失败，AFN: 0x{}", String.format("%02X", afn), e);
            return null;
        }
    }

    /**
     * 创建通用消息对象（用于暂未实现具体类的AFN）
     * @param control 控制域
     * @param address 地址域
     * @param afn AFN码
     * @param userData 用户数据
     * @return 通用消息对象
     */
    private static Message createGenericMessage(byte control, byte[] address, byte afn, byte[] userData) {
        return new GenericMessage(control, address, afn, userData);
    }

    /**
     * 通用消息类，用于处理暂未实现具体类的报文
     */
    public static class GenericMessage extends Message {
        public GenericMessage(byte control, byte[] address, byte afn, byte[] userData) {
            super(control, address, afn, userData);
        }

        @Override
        public String toString() {
            return "GenericMessage{" +
                    "control=" + String.format("0x%02X", getControl()) +
                    ", address=" + getAddressString() +
                    ", afn=" + String.format("0x%02X", getAfn()) +
                    ", userDataLength=" + getUserData().length +
                    '}';
        }
    }

    /**
     * 检查AFN是否被支持
     * @param afn AFN码
     * @return true表示支持，false表示不支持
     */
    public static boolean isAfnSupported(byte afn) {
        switch (afn) {
            case FrameConstants.AFN_REGISTER:
            case FrameConstants.AFN_REGISTER_CONFIRM:
            case FrameConstants.AFN_BALANCE_QUERY:
            case FrameConstants.AFN_RECHARGE:
            case FrameConstants.AFN_WATER_ELECTRICITY_PRICE_QUERY:
            case FrameConstants.AFN_OPEN_CARD:
                return true;
            default:
                return false;
        }
    }
}

